#include "BondDetailPrcFilterList.h"
#include "../QbBondModule.h"
#include "../BondDataCenter.h"
#include "../BondColDelegate.h"
#include "../StringResource.h"
#include "../GridImage.h"
#include "../BondUtility.h"
#include "../Detail/BondDetailTools.h"
#include <bondlib/SSVContainer.h>
#include <qbtools/tools.h>
#include <bondlib/BondCDCPriceInfo.h>
#include <bondlib/BondDict.h>
#include <bondlib/BondCalendar.h>
#include <guiframe/IModule.h>
#include <core/StyleMgr.h>
#include <core/time/system_time.h>
#include <include/CmdDefines.h>
#include <widgets/table/STable.h>
#include <widgets/table/STableColumnSet.h>
#include <QVBoxLayout>
#include <QTableView>
#include <QHeaderView>
#include <algorithm>

#define NOMINMAX

BondDetailPrcFilterList::BondDetailPrcFilterList(QWidget* p)
	:QWidget(p)
{
	m_table = new SVirtualTable(this);
	m_model = new DefaultTableModel(this);
	m_model->setTable(m_table);
	m_table->setHeaderSortable(true);
	m_table->table()->setModel(m_model);
	m_table->table()->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
	m_table->table()->horizontalHeader()->setSectionsMovable(true);
	m_table->table()->horizontalHeader()->show();
	m_table->table()->setContextMenuPolicy(Qt::CustomContextMenu);

	connect(m_table, &SVirtualTable::headerSort, this, &BondDetailPrcFilterList::onHeaderSort);//标题排序
	connect(m_table->table(), &QTableView::doubleClicked, this, &BondDetailPrcFilterList::onTableRowDblClicked);//双击
	connect(m_table->table(), &QTableView::clicked, this, &BondDetailPrcFilterList::onTableRowClicked);//单击

	QVBoxLayout* mainLayout = new QVBoxLayout(this);
	mainLayout->setContentsMargins(0, 0, 0, 0);
	mainLayout->addWidget(m_table);
	setLayout(mainLayout);
	setBrokerKey(-1, "");

}

void BondDetailPrcFilterList::UpdateResult(int currentType, std::vector<BrokerKey> &vctBondValid)
{
	m_ntabType = (tabType)currentType; //类型赋值
	sortCurrent((VSortKey)m_sortInfo.sortKey,m_sortInfo.bSort,vctBondValid);
	if (m_ntabType == relevanceFirst) //一级券不进行排序
		m_CurrentBondValid = vctBondValid;
	initListTitle();
	updateTable(true);
}

void BondDetailPrcFilterList::initListTitle()
{
	DefaultTableModel* dataModel = dynamic_cast<DefaultTableModel*>(m_table->table()->model());
	if (!dataModel)  return;

	for (size_t nCol = 0; nCol < m_cols.size(); nCol++)
	{
		ColumnInfo ci = m_tableSet->colInfoByIndex(nCol);
		if (m_sortInfo.nSortCol == nCol)
		{
			QString prefix = "";
			m_sortInfo.bSort == true ? prefix = "↓" : prefix ="↑";
			dataModel->setHeaderData(nCol, Qt::Horizontal, prefix + ci.name);
		}
		else {
			dataModel->setHeaderData(nCol, Qt::Horizontal,  ci.name);
		}
	}
}

void BondDetailPrcFilterList::sortCurrent(VSortKey sortKey, bool bSort, std::vector<BrokerKey> &vcrCurrentBondValid)
{
	if (sortKey == VBOND_NULL)	return;
	CSSVContainer container;
	SSBrokerKeyVector vecTemp;
	int nSz = vcrCurrentBondValid.size();
	for (int i = 0; i < nSz; i++)
	{
		vecTemp.Insert(vcrCurrentBondValid[i]);
	}
	container.ss_sort(vecTemp, sortKey, "", bSort, false);
	m_CurrentBondValid = vecTemp.m_vct;
}

void BondDetailPrcFilterList::getIssurerType(CBondInfo* pInfo, QString& strType)
{
	strType = "--";
	if (!pInfo || !pInfo->IsValidBond())
		return;

	BondDict bdDict;
	CBondDict::instance().GetBondDict("institution_subtype", pInfo->GetInstitutionType(), bdDict);
	strType = QString::fromLocal8Bit(bdDict.selective_content);
	if (strType.isEmpty())
		strType = "--";
}

void BondDetailPrcFilterList::setBrokerKey(int nID, const char* cBroker)
{
	m_nbrokerKey.m_nIndex = nID;
	m_nbrokerKey.SetBrokerId(cBroker);
}

void BondDetailPrcFilterList::updatePrcTable()
{
	updateTable(true);
}

void BondDetailPrcFilterList::onHeaderSort(int col)
{
	if (m_ntabType < relevanceIssure || m_ntabType > relevanceFirst) return;
	VSortKey sortKey;
	if (m_ntabType == relevanceSecond)
	{
		switch (col)
		{
		case RelevanceSecondList::rSeCol_RESTIME:
			sortKey = VEXPIRY_DATE;
			break;
		case RelevanceSecondList::rSeCol_CODE:
			sortKey = VBOND_CODE;
			break;
		case RelevanceSecondList::rSeCol_NAME:
			sortKey = VSHORT_NAME;
			break;
		case RelevanceSecondList::rSeCol_COMPANYTYPE:
			sortKey = INSTITUTION_TYPE;
			break;
		case RelevanceSecondList::rSeCol_BID:
			sortKey = VBUYPRICE;
			break;
		case RelevanceSecondList::rSeCol_OFR:
			sortKey = VSELLPRICE;
			break;
		case RelevanceSecondList::rSeCol_DEALPRICE:
			sortKey = VTKNPRICE;
			break;
		case RelevanceSecondList::rSeCol_ISSURERTNG:
			sortKey = VESTBPRICEPRE;
			break;
		case RelevanceSecondList::rSeCol_BONDRATE:
			sortKey = VRATING;
			break;
		case RelevanceSecondList::rSeCol_UPDATETIME:
			sortKey = VMODIFY_TIME;
			break;
		default:
			break;
		}
	}
	else if (m_ntabType == relevanceFirst)
	{
		switch (col)
		{
		case RelevanceFirstList::rFCol_CODE:
			sortKey = VBOND_CODE;
			break;
		case RelevanceFirstList::rFCol_NAME:
			sortKey = VSHORT_NAME;
			break;
		case RelevanceFirstList::rFCol_COMPANYTYPE:
			sortKey = INSTITUTION_TYPE;
			break;
		case RelevanceFirstList::rFCol_MATURITY:
			sortKey = MATURITY_TERM_END;
			break;
		case RelevanceFirstList::rFCol_ISSUREDAY:
			sortKey = ISSUE_START_DATE;
			break;
		case RelevanceFirstList::rFCol_COUPONRATE:
			sortKey = COUPON_RATE;
			break;
		case RelevanceFirstList::rFCol_OFFERINGAMOUNT:
			sortKey = PLANNED_ISSURE_AMOUNT;
			break;
		case RelevanceFirstList::rFCol_ISSURERTNG:
			sortKey = VRATING;
			break;
		default:
			break;
		}
	}
	else if (m_ntabType == relevanceIssure)
	{
		switch (col)
		{
		case SameIssurerList::priCol_RESTIME:
			sortKey = VEXPIRY_DATE;
			break;
		case SameIssurerList::priCol_CODE:
			sortKey = VBOND_CODE;
			break;
		case SameIssurerList::priCol_NAME:
			sortKey = VSHORT_NAME;
			break;
		case SameIssurerList::priCol_BID:
			sortKey = VBUYPRICE;
			break;
		case SameIssurerList::priCol_OFR:
			sortKey = VSELLPRICE;
			break;
		case SameIssurerList::priCol_DEALPRICE:
			sortKey = VTKNPRICE;
			break;
		case SameIssurerList::priCol_COUPONRATE:
			sortKey = COUPON_RATE;
			break;
		case SameIssurerList::priCol_ISSUREDAY:
			sortKey = ISSUE_START_DATE;
			break;
		case SameIssurerList::priCol_BONDRATE:
			sortKey = VRATING;
			break;
		case SameIssurerList::priCol_CDC:
			sortKey = VESTBPRICEPRE;
			break;
		case SameIssurerList::priCol_UPDATETIME:
			sortKey = VMODIFY_TIME;
			break;
		default:
			break;
		}
	}
	m_sortInfo.sortKey = sortKey;
	m_sortInfo.bSort = !m_sortInfo.bSort;
	m_sortInfo.nSortCol = col;
	sortCurrent(sortKey, m_sortInfo.bSort, m_CurrentBondValid);
	initListTitle();
	updateTable(true);
}

void BondDetailPrcFilterList::onTableRowDblClicked(const QModelIndex& index)
{
	QString strKey = index.data(DataIdRole).toString();
	const char* sKey = strKey.toStdString().c_str();
	int bondIndex = CBondContainer::instance().GetBondIndex(sKey);
	if (!CBondContainer::instance().IsValidIndex(bondIndex))
		return;

	QbBondModule::instance().app()->execCommand(CMD_BondDetail, sKey);
}

void BondDetailPrcFilterList::onTableRowClicked(const QModelIndex& index)
{
	int nRow = index.row();
	int nCol = index.column();

	int nRowCount = m_model->rowCount();
	int nColCount = m_model->columnCount();

	if (nRow < 0 || nRow >= nRowCount || nCol < 0 || nCol >= nColCount)	return;

	m_bfirstClicked = true;

	QString strBroker = "";
	if (m_ntabType == relevanceSecond)
		strBroker = index.data(BrokerIdRole).toString();

	QString strKey = index.data(DataIdRole).toString();
	std::string combKey = strKey.toStdString();
	/*const char* combKey = strKey.toStdString().c_str();*/
	int bondIndex = CBondContainer::instance().GetBondIndex(combKey);
	if (CBondContainer::instance().IsValidIndex(bondIndex))
	{
		setBrokerKey(bondIndex, strBroker.toStdString().c_str());
	}
	emit bondSelected(combKey);
}

void BondDetailPrcFilterList::onBestPricePush(QList<xQBBestPriceUnit_c> list)
{
	bool changed = false;
	for (auto& it : list)
	{
		QString key = QString("%1.%2").arg(it.m_bondkey).arg(it.m_listedmarket);
		for (auto& bond : m_CurrentBondKeys)
		{
			if (bond == key)
			{
				changed = true;
				break;
			}
		}
		if(changed)
			break;
	}

	if (changed)
	{
		UpdateResult(m_ntabType,m_CurrentBondValid);
	}
}

void BondDetailPrcFilterList::onDealMarketPushAll(int funid,QList<xQBMarketStreamUnit_c> marketList)
{
	bool changed = false;
	for (auto& it : marketList)
	{
		QString key = QString("%1.%2").arg(it.m_body2.m_bondkey).arg(it.m_body2.m_listedmarket);
		for (auto& bond : m_CurrentBondKeys)
		{
			if (bond == key)
			{
				changed = true;
				break;
			}
		}
		if (changed)
			break;
	}
	if (changed)
	{
		UpdateResult(m_ntabType, m_CurrentBondValid);
	}
}

//////////////////////////////////////////////////////////////////////////
SameIssurerList::SameIssurerList(QWidget* p)
	: BondDetailPrcFilterList(p)
{
	initTable();
	m_sortInfo.bSort = true;
	m_sortInfo.sortKey = VMODIFY_TIME;
	m_sortInfo.nSortCol = SameIssurerList::priCol_UPDATETIME;
	m_sortInfo.nPreSortCol = SameIssurerList::priCol_UPDATETIME;

	initListTitle();
	RemainDateDelegate* sameIssurerDelegate = new RemainDateDelegate(m_table, m_tableSet,BottomCursor);
	m_table->table()->setItemDelegateForColumn(priCol_RESTIME, sameIssurerDelegate);
	connect(&BondDataCenter::instance(), &BondDataCenter::bestPriceArrivedAll, this, &BondDetailPrcFilterList::onBestPricePush);//50903
	connect(&BondDataCenter::instance(), &BondDataCenter::dealMarketPushAll, this, &BondDetailPrcFilterList::onDealMarketPushAll);//50061
}

void SameIssurerList::initTable()
{
#define ALIGN_RIGHT  (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignRight)
#define ALIGN_LEFT  (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignLeft)
#define ALIGN_CENTER  (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignCenter)

	m_tableSet = new STableColumnSet(m_table, "primaryReleIssuersList", this);
	m_tableSet->setSaveCfg(true);

	BEGIN_COLUMN;
	ADD_COLUMN(0, m_tableSet, tr("剩余期限"), 0, 40, 40, 0.111, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(priCol_RESTIME);
	ADD_COLUMN(1, m_tableSet, tr("代码"), 0, 40, 40, 0.1314, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(priCol_CODE);
	ADD_COLUMN(2, m_tableSet, tr("简称"), 0, 40, 40, 0.1314, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(priCol_NAME);
	ADD_COLUMN(3, m_tableSet, tr("Bid"), 0, 40, 40, 0.074, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(priCol_BID);
	ADD_COLUMN(4, m_tableSet, tr("Ofr"), 0, 40, 40, 0.074, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(priCol_OFR);
	ADD_COLUMN(5, m_tableSet, tr("成交价"), 0, 40, 40, 0.0813, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(priCol_DEALPRICE);
	ADD_COLUMN(6, m_tableSet, tr("票面利率"), 0, 40, 40, 0.10, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(priCol_COUPONRATE);
	ADD_COLUMN(7, m_tableSet, tr("发行日"), 0, 40, 40, 0.10, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(priCol_ISSUREDAY);
	ADD_COLUMN(8, m_tableSet, tr("主/债"), 0, 40, 40, 0.10, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(priCol_BONDRATE);
	ADD_COLUMN(9, m_tableSet, tr("中债估值"), 0, 40, 40, 0.10, false, ALIGN_RIGHT, kAuto, "");
	m_cols.push_back(priCol_CDC);
	ADD_COLUMN(10, m_tableSet, tr("更新时间"), 0, 40, 40, 0.12, false, ALIGN_RIGHT, kAuto, "");
	m_cols.push_back(priCol_UPDATETIME);
	m_tableSet->apply();
	m_tableSet->setMenuCfg(KALl);

	connect(m_table, &SVirtualTable::viewPosChanged, [=](int){	updateTable(false);});
}

void SameIssurerList::updateTable(bool reset)
{
	m_table->clearTable();
	QFont f = font();
	f.setPixelSize(13);
	f.setBold(true);
	
	int npageCount = m_table->pageCount();
	int nDataCount = m_CurrentBondValid.size();
#ifdef WIN32
	npageCount = min(npageCount,nDataCount);
#else
	npageCount = std::min(npageCount,nDataCount);
#endif
	int pos = reset ? 0 : m_table->sliderPos();
	m_table->setRealDataCount(nDataCount);

	CBondInfo* pInfo;
	char cBroker[12] = { 0 };
	char cDonePrice[12] = { 0 };
	MarketInfo marketInfo;
	REPORT rpt;
	m_CurrentBondKeys.clear();
	for (int row = 0; row < npageCount; ++row)
	{
		if (pos + row >= (int)m_CurrentBondValid.size())
			return;

		const BrokerKey& brokerInfo = m_CurrentBondValid[row + pos];
		int nBondIndex = brokerInfo.m_nIndex;
		pInfo = CSSVContainer::availableBond().GetBond(nBondIndex);
		if (!pInfo || !pInfo->IsValidBond()) continue;
		FIELDCOPY(cBroker, brokerInfo.GetBrokerId().c_str());
		memset(&rpt, 0, sizeof(REPORT));
		FIELDCOPY(rpt.m_company_id, brokerInfo.GetBrokerId().c_str());
		FIELDCOPY(cDonePrice, "");
		memset(&marketInfo, 0, sizeof(MarketInfo));

		QString comboKey = pInfo->GetCombBondKey();
		m_CurrentBondKeys.push_back(comboKey);
		
		if (atoi(cBroker) != m_gErrorBroker)
		{
			CBondContainer::instance().GetCompanyRepByKey(pInfo->GetCombBondKey(), cBroker, rpt);
			SCOPED_MUTEX(CMarketStream::bondStream().GetMutex());
			if (CMarketStream::bondStream().GetMarketStreamByKey(pInfo->GetCombBondKey(), cBroker, marketInfo))
			{
				FIELDCOPY(cDonePrice, marketInfo.m_body.m_price);
			}
		}
		for (int col = 0; col < m_model->columnCount(); ++col)
		{
			if (!m_tableSet->isColVisible(col))
				continue;
			QStandardItem* item = m_model->item(row, col);
			QString strTemp = "";
			item->clearData();
			item->setData(StyleMgr::instance().color("Highlight"), Qt::ForegroundRole);
			item->setData((int)(Qt::AlignLeft | Qt::AlignVCenter), Qt::TextAlignmentRole);
			item->setData(StyleMgr::instance().color("BasicPlate"), Qt::BackgroundRole);
			item->setFont(f);

			QString comboKey = pInfo->GetCombBondKey();
			item->setData(comboKey, DataIdRole);

			if (col == priCol_RESTIME) //剩余期限
			{
				strTemp = QString::asprintf("%s",pInfo->GetRemainPeriod(CSSVContainer::GetServerTime()));
				item->setData(strTemp, Qt::DisplayRole);

				int holidayType = emHolidayNull;
				QString strHolidayDays;
				bool isCIB = true;
				int nDayCIB = 0, nDaySSE = 0;
				if (CBondCalendar::instance().IsHoliday_CHY(*pInfo, isCIB, nDayCIB, nDaySSE))
				{
					if (isCIB)
					{
						if (nDayCIB == nDaySSE)
							strHolidayDays = QString::number(nDayCIB);
						else
							strHolidayDays = QString("%1/%2").arg(nDayCIB).arg(nDaySSE);
						holidayType = emHolidayCib;
					}
					else
					{
						holidayType = emHolidaySSE;
						strHolidayDays = QString::number(nDaySSE);
					}
					item->setData(holidayType, HolidayTypeRole);			//存休息类型
					item->setData(strHolidayDays, HolidayNumberRole);	//存休息时间

					int maturityDay = atoi(pInfo->GetMaturityDate());
					item->setData(maturityDay, MaturityDayRole);
				}
			}
			if (col == priCol_CODE)//代码
			{
				strTemp = QString::asprintf("%s" , pInfo->GetCombBondCode());			
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == priCol_NAME)//简称
			{
				strTemp = QString::fromLocal8Bit(pInfo->GetBondShortName());
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == priCol_BID)//BID
			{
				item->setData(StyleMgr::instance().color("Bid_GVN_H1"), Qt::ForegroundRole);
				strTemp = "--";
				if (strcmp(rpt.m_bidinfo.m_price_status, "0") != 0 && strcmp(rpt.m_bidinfo.m_sPrice, "") != 0)
				{
					if (strcmp(rpt.m_bidinfo.m_sPrice, "Bid") == 0)
					{
						strTemp = "Bid";
					}
					else
					{
						strTemp = SSTools::FormatePrice(rpt.m_bidinfo.m_sPrice);
					}
				}
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == priCol_OFR) //ofr
			{
				item->setData(StyleMgr::instance().color("Ofr_TKN_H1"), Qt::ForegroundRole);
				strTemp = "--";
				if (strcmp(rpt.m_askinfo.m_price_status, "0") != 0 && strcmp(rpt.m_askinfo.m_sPrice, "") != 0)
				{
					if (strcmp(rpt.m_askinfo.m_sPrice, "Ofr") == 0)
					{
						strTemp = "Ofr";
					}
					else
					{
					strTemp = SSTools::FormatePrice(rpt.m_askinfo.m_sPrice);
					}
				}
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == priCol_DEALPRICE)
			{
			if (strlen(cDonePrice) > 0 && atof(cDonePrice) > 0.01)
			{
				strTemp = SSTools::FormatePrice(cDonePrice);
			}
			if (strTemp.isEmpty())
			{
				strTemp = ("--");
			}
			item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == priCol_COUPONRATE)
			{
			if (strlen(pInfo->GetCouponRateCurrent()) <= 0)
			{
				strTemp = "--";
			}
			else
			{
				strTemp = BondUtility::FormatBidLimitTop((pInfo->GetCouponRateCurrent()));
			}
			item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == priCol_ISSUREDAY) {
			if (strlen(pInfo->GetIssueStartDate()) > 0) {
				int nYears, nMonths, nDays;
				sscanf(pInfo->GetIssueStartDate(), "%04d%02d%02d", &nYears, &nMonths, &nDays);
				strTemp = QString::asprintf("%d-%d-%d", nYears, nMonths, nDays);
			}
			item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == priCol_BONDRATE) {
			strTemp = QString::asprintf("%s", pInfo->GetIssuerBondRating());
			if (strTemp.isEmpty()) strTemp = "--";
			item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == priCol_CDC)
			{
				item->setData((int)(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
				bool bIsCDCAuthValid = pInfo->IsCDCAuthValid();
				bool bHasCDCRights = SSUserAccountManager::instance().HasAnyCDCAuthority();
				if (!bHasCDCRights && !bIsCDCAuthValid)
				{
					strTemp = "";
				}
				else
				{
					int nOptType = CBondCDCPriceInfo::est_type_invalid;
					strTemp = QString::asprintf("%s", CBondCDCPriceInfo::instance().GetCDCPriceYesterday(nOptType, bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, false).c_str());
					if (strTemp.isEmpty()) strTemp = "--";
					//中债估值 含权,显示三角形和tip
					switch (nOptType)
					{
						case CBondCDCPriceInfo::est_type_combine:
						case CBondCDCPriceInfo::est_type_exercise:
						case CBondCDCPriceInfo::est_type_expire:
						{
							item->setData(NewStringTable::strEstRemark(nOptType + 1) + '\n' + strTemp, Qt::ToolTipRole);
							item->setData(BondUtility::gridImage(grid_flag_triangle), Qt::DecorationRole);
							break;
						}
						default:
						{
							break;
						}
					}
				}
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == priCol_UPDATETIME)
			{
			item->setData((int)(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
#ifdef WIN32
			time_t tTime = max(rpt.m_time, max(max(rpt.m_create_time, marketInfo.m_create_time), marketInfo.m_modify_time));
#else
                        time_t tTime = std::max(
                            (int)rpt.m_time,
                            std::max(std::max((int)rpt.m_create_time,
                                              (int)marketInfo.m_create_time),
                                     (int)marketInfo.m_modify_time));
#endif
			if (tTime > 0)
			{
				qb::base::CTime stTime(tTime);
				qb::base::CTime stTimeTemp(stTime.GetYear(), stTime.GetMonth(), stTime.GetDay(), 23, 59, 59);
				if (CSSVContainer::GetServerTime() > stTimeTemp.GetTime())
				{//过去的数据
					strTemp = NewStringTable::strYearMonthDay(stTime);
				}
				else
				{
					strTemp = QString::asprintf("%02d:%02d:%02d", stTime.GetHour(), stTime.GetMinute(), stTime.GetSecond());
				}
			}
			if (strTemp.isEmpty()) strTemp = "--";
			item->setData(strTemp, Qt::DisplayRole);
			}
			m_model->setItem(row, col, item);
		}
	}
	if (!m_bfirstClicked && !m_CurrentBondValid.empty())
		onTableRowClicked(m_model->index(0, 0, QModelIndex())); //代表默认点击第一行
}

//////////////////////////////////////////////////////////////////////////
RelevanceSecondList::RelevanceSecondList(QWidget* p)
	: BondDetailPrcFilterList(p)
{
	initTable();
	m_sortInfo.bSort = true;
	m_sortInfo.sortKey = VMODIFY_TIME;
	m_sortInfo.nSortCol = RelevanceSecondList::rSeCol_UPDATETIME;
	m_sortInfo.nPreSortCol = RelevanceSecondList::rSeCol_UPDATETIME;
	initListTitle();
	RemainDateDelegate* relevanceSecondDelegate = new RemainDateDelegate(m_table, m_tableSet,BottomCursor);
	m_table->table()->setItemDelegateForColumn(rSeCol_RESTIME, relevanceSecondDelegate);

	connect(&BondDataCenter::instance(), &BondDataCenter::bestPriceArrivedAll, this, &BondDetailPrcFilterList::onBestPricePush);
	connect(&BondDataCenter::instance(), &BondDataCenter::dealMarketPushAll, this, &BondDetailPrcFilterList::onDealMarketPushAll);
}

void RelevanceSecondList::initTable()
{
#define ALIGN_RIGHT  (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignRight)
#define ALIGN_LEFT  (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignLeft)
#define ALIGN_CENTER  (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignCenter)

	m_tableSet = new STableColumnSet(m_table, "primaryReleSecondList", this);
	m_tableSet->setSaveCfg(true);

	BEGIN_COLUMN;
	ADD_COLUMN(0, m_tableSet, tr("剩余期限"), 0, 40, 40, 0.12, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rSeCol_RESTIME);
	ADD_COLUMN(1, m_tableSet, tr("代码"), 0, 40, 40, 0.12, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rSeCol_CODE);
	ADD_COLUMN(2, m_tableSet, tr("简称"), 0, 40, 40, 0.1166, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rSeCol_NAME);
	ADD_COLUMN(3, m_tableSet, tr("Bid"), 0, 40, 40, 0.11, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rSeCol_BID);
	ADD_COLUMN(4, m_tableSet, tr("Ofr"), 0, 40, 40, 0.11, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rSeCol_OFR);
	ADD_COLUMN(5, m_tableSet, tr("成交价"), 0, 40, 40, 0.11, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rSeCol_DEALPRICE);
	ADD_COLUMN(6, m_tableSet, tr("估值"), 0, 40, 40, 0.10, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rSeCol_ISSURERTNG);
	ADD_COLUMN(7, m_tableSet, tr("企业类型"), 0, 40, 40, 0.14, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rSeCol_COMPANYTYPE);
	ADD_COLUMN(8, m_tableSet, tr("主/债"), 0, 40, 40, 0.1032, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rSeCol_BONDRATE);
	ADD_COLUMN(9, m_tableSet, tr("更新时间"), 0, 40, 40, 0.09, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rSeCol_UPDATETIME);
	m_tableSet->apply();
	m_tableSet->setMenuCfg(KALl);

	connect(m_table, &SVirtualTable::viewPosChanged, [=](int){updateTable(false);});
}

void RelevanceSecondList::updateTable(bool reset)
{
	m_table->clearTable();

	QFont f = font();
	f.setPixelSize(13);
	f.setBold(true);

	int npageCount = m_table->pageCount();
	int nDataCount = m_CurrentBondValid.size();
	int pos = reset ? 0 : m_table->sliderPos();
	m_table->setRealDataCount(nDataCount);
	CBondInfo* pInfo = nullptr;
	char cBroker[12] = { 0 };
	char cDonePrice[12] = { 0 };
	MarketInfo marketInfo;
	REPORT rpt;
	m_CurrentBondKeys.clear();
	for (int row = 0; row < m_table->pageCount() && row + pos < (int)m_CurrentBondValid.size(); row++)
	{
		const BrokerKey& brokerInfo = m_CurrentBondValid[row + pos];
		int nBondIndex = brokerInfo.m_nIndex;
		pInfo = CSSVContainer::availableBond().GetBond(nBondIndex);
		if (!pInfo || !pInfo->IsValidBond()) continue;
		FIELDCOPY(cBroker, brokerInfo.GetBrokerId().c_str());
		memset(&rpt, 0, sizeof(REPORT));
		FIELDCOPY(rpt.m_company_id, brokerInfo.GetBrokerId().c_str());
		FIELDCOPY(cDonePrice, "");
		memset(&marketInfo, 0, sizeof(MarketInfo));

		QString comboKey = pInfo->GetCombBondKey();
		m_CurrentBondKeys.push_back(comboKey);
		
		if (atoi(cBroker) != m_gErrorBroker)
		{
			CBondContainer::instance().GetCompanyRepByKey(pInfo->GetCombBondKey(), cBroker, rpt);
			SCOPED_MUTEX(CMarketStream::bondStream().GetMutex());
			if (CMarketStream::bondStream().GetMarketStreamByKey(pInfo->GetCombBondKey(), cBroker, marketInfo))
			{
				FIELDCOPY(cDonePrice, marketInfo.m_body.m_price);
			}
		}
		for (int col = 0; col < m_model->columnCount(); col++)
		{
			if (!m_tableSet->isColVisible(col))
				continue;
			QStandardItem* item = m_model->item(row, col);
			QString strTemp = "";
			item->clearData();
			item->setData(StyleMgr::instance().color("Highlight"), Qt::ForegroundRole);
			item->setData((int)(Qt::AlignLeft | Qt::AlignVCenter), Qt::TextAlignmentRole);
			item->setData(StyleMgr::instance().color("BasicPlate"), Qt::BackgroundRole);
			item->setFont(f);

			QString comboKey = pInfo->GetCombBondKey();
			item->setData(comboKey, DataIdRole);
			
			int nbrokerValue = atoi(cBroker);
			item->setData(nbrokerValue, BrokerIdRole);

			if (col == rSeCol_CODE)
			{
				strTemp = QString::asprintf("%s", pInfo->GetCombBondCode());
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rSeCol_NAME)
			{
				strTemp = QString::fromLocal8Bit(pInfo->GetBondShortName());
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rSeCol_RESTIME)
			{
				strTemp = QString::asprintf("%s", pInfo->GetRemainPeriod(CSSVContainer::GetServerTime()));
				item->setData(strTemp, Qt::DisplayRole);

				int holidayType = emHolidayNull;
				QString strHolidayDays;
				bool isCIB = true;
				int nDayCIB = 0, nDaySSE = 0;
				if (CBondCalendar::instance().IsHoliday_CHY(*pInfo, isCIB, nDayCIB, nDaySSE))
				{
					if (isCIB)
					{
						if (nDayCIB == nDaySSE)
							strHolidayDays = QString::number(nDayCIB);
						else
							strHolidayDays = QString("%1/%2").arg(nDayCIB).arg(nDaySSE);
						holidayType = emHolidayCib;
					}
					else
					{
						holidayType = emHolidaySSE;
						strHolidayDays = QString::number(nDaySSE);
					}
					item->setData(holidayType, HolidayTypeRole);			//存休息类型
					item->setData(strHolidayDays, HolidayNumberRole);	//存休息时间

					int maturityDay = atoi(pInfo->GetMaturityDate());
					item->setData(maturityDay, MaturityDayRole);
				}
			}
			else if (col == rSeCol_BID)
			{
				item->setData(StyleMgr::instance().color("Bid_GVN_H1"), Qt::ForegroundRole);
				strTemp = "--";
				if (strcmp(rpt.m_bidinfo.m_price_status, "0") != 0 && strcmp(rpt.m_bidinfo.m_sPrice, "") != 0)
				{
					if (strcmp(rpt.m_bidinfo.m_sPrice, "Bid") == 0)
					{
						strTemp = "Bid";
					}
					else
					{
						strTemp = SSTools::FormatePrice(rpt.m_bidinfo.m_sPrice);
					}
				}
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rSeCol_OFR)
			{
				item->setData(StyleMgr::instance().color("Ofr_TKN_H1"), Qt::ForegroundRole);
				strTemp = "--";
				if (strcmp(rpt.m_askinfo.m_price_status, "0") != 0 && strcmp(rpt.m_askinfo.m_sPrice, "") != 0)
				{
					if (strcmp(rpt.m_askinfo.m_sPrice, "Ofr") == 0)
					{
						strTemp = "Ofr";
					}
					else
					{
						strTemp = SSTools::FormatePrice(rpt.m_askinfo.m_sPrice);
					}
				}
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rSeCol_DEALPRICE)
			{
				if (strlen(cDonePrice) > 0 && atof(cDonePrice) > 0.01)
				{
					strTemp = SSTools::FormatePrice(cDonePrice);
				}
				if (strTemp.isEmpty())
					strTemp = "--";
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rSeCol_ISSURERTNG)
			{
				item->setData((int)(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
				bool bIsCDCAuthValid = pInfo->IsCDCAuthValid();
				bool bHasCDCRights = SSUserAccountManager::instance().HasAnyCDCAuthority();
				if (!bHasCDCRights && !bIsCDCAuthValid)
				{
					strTemp = "";
				}
				else
				{
					int nOptType = CBondCDCPriceInfo::est_type_invalid;
					strTemp = QString::asprintf("%s", CBondCDCPriceInfo::instance().GetCDCPriceYesterday(nOptType, bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, false).c_str());
					if (strTemp.isEmpty()) strTemp = "--";
					//中债估值 含权,显示三角形和tip
					switch (nOptType)
					{
						case CBondCDCPriceInfo::est_type_combine:
						case CBondCDCPriceInfo::est_type_exercise:
						case CBondCDCPriceInfo::est_type_expire:
						{
							item->setData(NewStringTable::strEstRemark(nOptType + 1) + '\n' + strTemp, Qt::ToolTipRole);
							item->setData(BondUtility::gridImage(grid_flag_triangle), Qt::DecorationRole);
							break;
						}
						default:
						{
							break;
						}
					}

				}
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rSeCol_COMPANYTYPE)
			{
				getIssurerType(pInfo, strTemp);
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rSeCol_BONDRATE)
			{
				strTemp = QString::asprintf("%s",pInfo->GetIssuerBondRating());
				if (strTemp.isEmpty())
					strTemp = "--";
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rSeCol_UPDATETIME)
			{
#ifdef WIN32
				time_t tTime = max(rpt.m_time, max(max(rpt.m_create_time, marketInfo.m_create_time), marketInfo.m_modify_time));
#else
                          time_t tTime =
                              std::max((int)rpt.m_time,
                              std::max(std::max((int)rpt.m_create_time,
                                                (int)marketInfo.m_create_time),
                                       (int)marketInfo.m_modify_time));
#endif
				if (tTime > 0)
				{
					qb::base::CTime stTime(tTime);
					qb::base::CTime stTimeTemp(stTime.GetYear(), stTime.GetMonth(), stTime.GetDay(), 23, 59, 59);
					if (CSSVContainer::GetServerTime() > stTimeTemp.GetTime())
					{//过去的数据
						strTemp = NewStringTable::strYearMonthDay(stTime);
					}
					else
					{
						strTemp = QString::asprintf("%02d:%02d:%02d", stTime.GetHour(), stTime.GetMinute(), stTime.GetSecond());
					}
				}
				item->setData(strTemp, Qt::DisplayRole);
			}
			m_model->setItem(row, col, item);
		}
	}
}

//////////////////////////////////////////////////////////////////////////
RelevanceFirstList::RelevanceFirstList(QWidget* p)
	: BondDetailPrcFilterList(p)
{
	initTable();
	m_sortInfo.bSort = true;
	m_sortInfo.sortKey = VBOND_NULL;
	m_sortInfo.nSortCol = -1;
	m_sortInfo.nPreSortCol = -1;
	initListTitle();
}

void RelevanceFirstList::initTable()
{
#define ALIGN_RIGHT  (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignRight)
#define ALIGN_LEFT  (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignLeft)
#define ALIGN_CENTER  (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignCenter)

	m_tableSet = new STableColumnSet(m_table, "primaryReleFirstList", this);
	m_tableSet->setSaveCfg(true);

	BEGIN_COLUMN;
	ADD_COLUMN(0, m_tableSet, tr("代码"), 0, 40, 40, 0.18, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rFCol_CODE);
	ADD_COLUMN(1, m_tableSet, tr("简称"), 0, 40, 40, 0.21, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rFCol_NAME);
	ADD_COLUMN(2, m_tableSet, tr("期限"), 0, 40, 40, 0.10, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rFCol_MATURITY);
	ADD_COLUMN(3, m_tableSet, tr("发行日"), 0, 40, 40, 0.14, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rFCol_ISSUREDAY);
	ADD_COLUMN(4, m_tableSet, tr("票面利率"), 0, 40, 40, 0.120, false, ALIGN_RIGHT, kAuto, "");
	m_cols.push_back(rFCol_COUPONRATE);
	ADD_COLUMN(5, m_tableSet, tr("发行量(亿)"), 0, 40, 40, 0.140, false, ALIGN_RIGHT, kAuto, "");
	m_cols.push_back(rFCol_OFFERINGAMOUNT);
	ADD_COLUMN(6, m_tableSet, tr("企业类型"), 0, 40, 40, 0.15, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rFCol_COMPANYTYPE);
	ADD_COLUMN(7, m_tableSet, tr("主/债"), 0, 40, 40, 0.110, false, ALIGN_LEFT, kAuto, "");
	m_cols.push_back(rFCol_ISSURERTNG);
	m_tableSet->apply();
	m_tableSet->setMenuCfg(KALl);

	connect(m_table, &SVirtualTable::viewPosChanged, [=](int)
		{
					updateTable(false);
		});
}

void RelevanceFirstList::updateTable(bool reset)
{
	m_table->clearTable();

	QFont f = font();
	f.setPixelSize(13);
	f.setBold(true);

	int npageCount = m_table->pageCount();
	int nDataCount = m_CurrentBondValid.size();
	int pos = reset ? 0 : m_table->sliderPos();
	m_table->setRealDataCount(nDataCount);
	CBondInfo* pInfo = nullptr;

	for (int row = 0; row < m_table->pageCount() && row + pos < (int)m_CurrentBondValid.size(); row++)
	{
		const BrokerKey& brokerInfo = m_CurrentBondValid[row + pos];
		int nBondIndex = brokerInfo.m_nIndex;
		pInfo = CSSVContainer::availableBond().GetBond(nBondIndex);
		if (!pInfo) continue;
		for (int col = 0; col < m_model->columnCount(); col++)
		{
			if (!m_tableSet->isColVisible(col))
				continue;
			QStandardItem* item = m_model->item(row, col);
			QString strTemp = "";
			item->clearData();
			item->setData(StyleMgr::instance().color("Highlight"), Qt::ForegroundRole);
			item->setData((int)(Qt::AlignLeft | Qt::AlignVCenter), Qt::TextAlignmentRole);
			item->setData(StyleMgr::instance().color("BasicPlate"), Qt::BackgroundRole);
			item->setFont(f);

			QString comboKey = pInfo->GetCombBondKey();
			item->setData(comboKey, DataIdRole);

			if (col == rFCol_CODE)
			{
				strTemp = QString::asprintf("%s", pInfo->GetCombBondCode());
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rFCol_NAME)
			{
				strTemp = QString::fromLocal8Bit(pInfo->GetBondShortName());
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rFCol_MATURITY)
			{
				strTemp = pInfo->GetTermToMaturity();
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rFCol_ISSUREDAY)
			{
				if (strlen(pInfo->GetIssueStartDate()) > 0)
				{
					int nYears, nMonths, nDays;
					sscanf(pInfo->GetIssueStartDate(), "%04d%02d%02d", &nYears, &nMonths, &nDays);
					strTemp = QString::asprintf("%d-%d-%d", nYears, nMonths, nDays);
				}
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rFCol_COUPONRATE)
			{
				item->setData((int)(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
				CBusinessShowInfo business;
				if (BondDetailTools::getEnablePucharceList(pInfo->GetCombBondKey(), business) && business.m_AllowList.size() > 0)
				{//TODO:HY数据类未迁移
					strTemp = "可申购";
				}
				else
				{
					if (strlen(pInfo->GetCouponRateCurrent()) <= 0)
					{
						strTemp = "--";
					}
					else
					{
						strTemp = BondUtility::FormatBidLimitTop(pInfo->GetCouponRateCurrent());
					}
				}
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rFCol_OFFERINGAMOUNT)
			{
				item->setData((int)(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
				strTemp = "--";
				if (pInfo->GetPlannedIssueAmount() > 100)
				{
					double dbPlan = pInfo->GetPlannedIssueAmount();
					dbPlan /= 10000;
					strTemp = QString::asprintf("%.2f", dbPlan);
				}
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rFCol_COMPANYTYPE)
			{
				getIssurerType(pInfo, strTemp);
				item->setData(strTemp, Qt::DisplayRole);
			}
			else if (col == rFCol_ISSURERTNG)
			{
				strTemp = QString::asprintf("%s", pInfo->GetIssuerBondRating());
				item->setData(strTemp, Qt::DisplayRole);
			}
			m_model->setItem(row, col, item);
		}
	}
}